#include "stdafx.h"
#include "materialeditor.h"

namespace Lit
{
	namespace Editor
	{
		MaterialEditor::MaterialEditor(bool standalone, QWidget *parent, Qt::WFlags flags)
			: QMainWindow(parent, flags)
			, mStandalone( standalone )
		{
			ui.setupUi(this);
			mRenderer  = ui.renderWidget;
			mLog = NULL;
			mProject = new Material::Project( &ui, qApp->arguments());
			mStartup = new Material::StartupDialog( this );

			mRenderer->addListener( this );
		}

		MaterialEditor::~MaterialEditor()
		{
			if( mProject ) delete mProject, mProject = NULL;
			if( mStartup ) delete mStartup, mStartup = NULL;
		}
		
		void MaterialEditor::mouseScrolled( int delta )
		{
			zoomCamera( delta>0?1.0f:-1.0f );
		}
		void MaterialEditor::wheelEvent( QWheelEvent * evt )
		{
			mouseScrolled(evt->delta());
		}
		
		bool MaterialEditor::isStandalone() const
		{
			return mStandalone;
		}
	
		bool MaterialEditor::frameStarted( const Ogre::FrameEvent &evt ){
			static bool g_first = false;
			if( g_first )
			{
				static bool first = true;
				if( first )
				{	
					if( !mProject->getCommandArguments().empty() )
					{
						mProject->openProject( mProject->getCommandArguments().at(0) );
					}
					else{
						mStartup->exec();
					}
					first = false;
				}
			}
			
			
			if( mLeftDrag.isDragging() )
			{
				mLeftDrag.step();
				Vec2 delta(mLeftDrag.getDelta());
				if( mLeftDrag.hasButton( Qt::RightButton ) )
				{
					if( mLeftDrag.hasButton( Qt::LeftButton ) ) zoomCamera( delta.y ); 
					else tiltCamera( delta.x, delta.y );
				}
				else if( mLeftDrag.hasButton( Qt::MidButton ) )
				{
					panCamera( delta.x, delta.y );
				}
				Ogre::LogManager::getSingleton().logMessage(String("Drag: ")(delta));
			}
			g_first = true;
			return true;
		}
		void MaterialEditor::createScene()
		{
#ifndef NDEBUG
			mLog = Ogre::LogManager::getSingleton().createLog("MaterialEditor_d.log", true);
#else
			mLog = Ogre::LogManager::getSingleton().createLog("MaterialEditor.log", true);
#endif
			mLog->logMessage( "Log Started on "+FROM_QT(QDate::currentDate().toString("dd/MM/yyyy")) );
			mLog->addListener( this );
			Ogre::Root::getSingleton().addFrameListener( this );

			mProject->createScene();

			std::string content = 
"void main( )\
{\
	System sys;\
	sys.logMessage(\"Hello From Script !\");\
}\
";
			FileStreamPtr strm( new FileStream( System::EditorPath() + "/test.as", FileStream::BinaryRead ) );
			ScriptEngine eng;
			ScriptModulePtr mod(eng.createModule( "global", SMF_ALWAYS_CREATE ));

			int r = mod->addSection( strm->getName(), content );
			if( r >= 0 ) r = mod->build();
			if( r >= 0 )
			{
				ScriptContextPtr ctx( eng.createContext() );
				ScriptContextState state = mod->execute( "void main()", ctx );
			}
		}
	
		void MaterialEditor::destroyScene()
		{
			mProject->destroyScene();
			Ogre::Root::getSingleton().removeFrameListener( this );
			mLog->removeListener( this );
		}
	
		void MaterialEditor::closeEvent( QCloseEvent * evt )
		{
			if( !mProject->closeProject() )
			{
				evt->ignore();
				return;
			}
			delete mRenderer, mRenderer = NULL;
			QMainWindow::closeEvent( evt );
		}
		
		void MaterialEditor::mousePressed(const QPoint& pos, Qt::MouseButtons btn)
		{
			mLeftDrag.start( btn );
		}
			
		void MaterialEditor::mouseReleased(const QPoint& pos, Qt::MouseButtons btn )
		{
			mLeftDrag.stop();
		}

		void MaterialEditor::panCamera( float dx, float dy )
		{
			Ogre::Camera * cam = ui.renderWidget->ogreCamera();
			Vec3 right( Quat( Ogre::Degree( 90.0f ), Vec3::UNIT_Y )* cam->getDerivedDirection() );
			cam->move( Vec3( right.x*dx, dy, right.z*dx ) );
		}

		void MaterialEditor::tiltCamera(  float yaw, float pitch )
		{
			Ogre::Camera * cam = ui.renderWidget->ogreCamera();
			Vec3 up( cam->getUp() );
			Vec3 right( cam->getRight() );
			cam->pitch( Ogre::Degree(pitch) );
			cam->yaw( Ogre::Degree(yaw) );
		}

		void MaterialEditor::zoomCamera( Real factor )
		{
			Vec3 dir(ui.renderWidget->ogreCamera()->getDirection());
			ui.renderWidget->ogreCamera()->move( dir * factor );
		}
		void MaterialEditor::updateUi()
		{
			bool c = mProject->isCreated();
			ui.actionSave_Project->setEnabled( c );
			ui.actionClose_Project->setEnabled( c );
			ui.actionCompile->setEnabled( c );
		}
		Material::Project * MaterialEditor::getProject(){ return mProject; }
		const Material::Project* MaterialEditor::getProject() const{ return mProject; }

		void MaterialEditor::on_actionNew_Project_triggered(){
			mProject->newProject( );
			updateUi();
		}
		void MaterialEditor::on_actionOpen_Project_triggered(){
			mProject->openProject();
			updateUi();
		}
		void MaterialEditor::on_actionSave_Project_triggered(){
			mProject->saveProject( );
			updateUi();
		}
		void MaterialEditor::on_actionSave_Project_As_triggered()
		{
			std::string fname = FileDialog::getSaveFileName( NULL, "Save Project As", FileSystem::applicationPath(), "Material Project File (*.matproj);;" );
			if( fname.empty() ) return;
			mProject->saveProject( fname );
			updateUi();
		}
		void MaterialEditor::on_actionClose_Project_triggered(){
			mProject->closeProject();
			updateUi();
		}
		void MaterialEditor::on_actionCompile_triggered(){
			mProject->compileProject();
		}
		void MaterialEditor::on_actionExit_triggered(){
			close();
		}
		void MaterialEditor::messageLogged( const Ogre::String &message, Ogre::LogMessageLevel lml, bool debugMask, const Ogre::String &filename )
		{
			if( debugMask )
			{
#ifndef NDEBUG
			ui.logOutput->appendPlainText( "[DEBUG] "+QTime::currentTime().toString("H:M:S")+": "+TO_QT(message) );
#endif
			}
			switch(lml)
			{
			case Ogre::LML_CRITICAL:
				ui.logOutput->appendPlainText( QTime::currentTime().toString("H:m:s")+": "+TO_QT(message) );
				break;
			case Ogre::LML_NORMAL:
				ui.logOutput->appendPlainText( QTime::currentTime().toString("H:m:s")+": "+TO_QT(message) );
				break;
			case Ogre::LML_TRIVIAL:
#ifndef NDEBUG
			ui.logOutput->appendPlainText( QTime::currentTime().toString("H:m:s")+": "+TO_QT(message) );
#endif
			};

		}
	};
};